package util;

import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;

import org.springframework.util.DigestUtils;

import freemarker.cache.StringTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateNotFoundException;

/**
 *
 * @类名称: XbellDynamicStringUtil
 * @描述: TODO 格式化sql，形成类似mybaits的方式，用于生成动态sql
 * @作者: 王文胜
 * @时间：2022年03月13日
 * @版本：V1.0
 */
public class XbellDynamicStringUtil {
	private static final XbellDynamicStringUtil builder = new XbellDynamicStringUtil();

	public static XbellDynamicStringUtil builder() {
		return builder;
	}
	/**
	 * 链式函数
	 * @author 王文胜
	 * @date 2023年7月5日 上午11:08:37
	 * @param map
	 * @param objs
	 * @return
	 */
	public XbellDynamicStringUtil addParam(Map<String,Object> map,Object ...objs)
	{
		XbellDynamicStringUtil.addParamIfNotBlank(map, objs);
		return this;
	}
	/**
	 * 链式函数
	 * @author 王文胜
	 * @date 2023年7月5日 上午11:08:46
	 * @param map
	 * @param objs
	 * @return
	 */
	public XbellDynamicStringUtil addLikeParam(Map<String,Object> map,Object ...objs)
	{
		XbellDynamicStringUtil.addLikeParamIfNotBlank(map, objs);
		return this;
	}
	/**
	 * 非链式函数
	 * @author 王文胜
	 * @date 2023年7月5日 上午11:08:52
	 * @param <T>
	 * @param sql
	 * @param params
	 * @param clz
	 * @param id
	 * @return
	 */
	public <T> String formatStr(String sql,Map<String,Object> params,Class<T> clz,final String id) {
		return XbellDynamicStringUtil.format(sql, params, clz, id);
	}

	public static Configuration cfg;
//	static
//	{
//		cfg = new Configuration(Configuration.VERSION_2_3_31);
//		cfg.setDefaultEncoding("UTF-8");
//		StringTemplateLoader strTmpLoader = new StringTemplateLoader();
//		cfg.setTemplateLoader(strTmpLoader);
//	}

	public static void setConfiguration(Configuration cfg) {
		XbellDynamicStringUtil.cfg = cfg;
	}
	public static Configuration getConfiguration() {
		if(cfg==null) {
			cfg = new Configuration(Configuration.VERSION_2_3_31);
			cfg.setDefaultEncoding("UTF-8");
			StringTemplateLoader strTmpLoader = new StringTemplateLoader();
			cfg.setTemplateLoader(strTmpLoader);
		}
		return cfg;
	}

	/**
	 * 格式化Sql,请尽量不要使用本方法
	 * @author 王文胜
	 * @date 2022年3月13日 - 上午1:30:50
	 * @copyright 合肥讯百软件科技有限公司
	 * @param <T>
	 * @param sql
	 * @param params 格式化参数
	 * @param clz 调用该方法的类
	 * @return
	 */
	private static <T> String format(String sql,Map<String,Object> params,Class<T> clz) {
		return format(sql,params,clz,null, false, null);
	}

	/**
	 * 格式化Sql
	 * @author GXY
	 * @date 2023年6月12日
	 * @copyright 合肥讯百软件科技有限公司
	 * @param <T>
	 * @param sql 要格式化的sql
	 * @param params 格式化参数
	 * @param clz 调用该方法的类
	 * @param id sql的id，防止重复
	 * @return
	 */
	public static <T> String format(String sql,Map<String,Object> params,Class<T> clz,final String id) {
		return format(sql,params,clz,null, false, null);
	}

	/**
	 * 格式化Sql
	 * @author 王文胜
	 * @date 2022年3月13日 - 上午1:30:50
	 * @copyright 合肥讯百软件科技有限公司
	 * @param <T>
	 * @param sql 要格式化的sql
	 * @param params 格式化参数
	 * @param clz 调用该方法的类
	 * @param id sql的id，防止重复
	 * @param addDataRange 是否增加数据范围
	 * @param refField addDataRange为ture时关联权限的字段，默认为bmdm
	 * @return
	 */
	public static <T> String format(String sql,Map<String,Object> params,Class<T> clz,final String id, boolean addDataRange, String refField) {
		if(clz==null) {
			throw new RuntimeException("未提供调用者");
		}
		if (addDataRange) {
		}
		getConfiguration();
		String name = clz.getCanonicalName()+"_"+(id==null?"":id.trim())+"_"+DigestUtils.md5DigestAsHex(sql.getBytes());
		try {
			Template tmp = null;
			try
			{
				tmp = cfg.getTemplate(name);
			}
			catch(TemplateNotFoundException ex) {
				StringTemplateLoader tl = (StringTemplateLoader)cfg.getTemplateLoader();
				tl.putTemplate(name, sql);
				cfg.clearTemplateCache();
				tmp = cfg.getTemplate(name);
			}
			StringWriter stringWriter = new StringWriter();
			tmp.process(params, stringWriter);
			return stringWriter.toString();
		}
		catch(Exception ex) {
			ex.printStackTrace();
			throw new RuntimeException("Sql语句生成失败");
		}
	}

	/**
	 * 添加参数，当value不是空或者空字符串时，以 key 作为名称，添加到map中
	 * @author 王文胜
	 * @date 2023年3月20日 下午4:30:20
	 * @param map
	 * @param objs key,value,key,value
	 * @return
	 */
	public static int addParamIfNotBlank(Map<String,Object> map,Object ...objs) {
		int c = 0;
		if(objs==null||objs.length==0) {
			return 0;
		}
		if(objs.length%2!=0) {
			throw new RuntimeException("参数个数必须为2的倍数");
		}
		for(int i=0;i<objs.length;i+=2) {
			String key = objs[i].toString();
			Object value_obj = objs[i+1];
			if(value_obj==null) {
				continue;
			}
			if(String.class.isAssignableFrom(value_obj.getClass())) {
				String value = (String)value_obj;
				if(value==null||value.trim().length()==0) {
					continue;
				}
				c++;
				map.put(key, value.trim());
			}
			else
				map.put(key, value_obj);
		}
		return c;
	}
	/**
	 * 添加like 参数
	 * @author 王文胜
	 * @date 2023年3月20日 下午4:48:41
	 * @param map 添加map
	 * @param key key
	 * @param value
	 * @return
	 */
	public static int addLikeParamIfNotBlank(Map<String,Object> map,Object ... objs) {
		//if(value==null||value.trim().length()==0) {
		//	return 0;
		//}
		//map.put(key, "%"+value.trim()+"%");
		//return 1;
		int c = 0;
		if(objs==null||objs.length==0) {
			return 0;
		}
		if(objs.length%2!=0) {
			throw new RuntimeException("参数个数必须为2的倍数");
		}
		for(int i=0;i<objs.length;i+=2) {
			String key = objs[i].toString();
			Object value_obj = objs[i+1];
			if(value_obj==null) {
				continue;
			}
			if(String.class.isAssignableFrom(value_obj.getClass())) {
				String value = (String)value_obj;
				if(value==null||value.trim().length()==0) {
					continue;
				}
				c++;
				map.put(key, "%"+value.trim()+"%");
			}
			else
				map.put(key, "%"+value_obj+"%");
		}
		return c;
	}

	/**
	 * 构建map，添加参数
	 * @author 王文胜
	 * @date 2023年6月1日 下午1:55:15
	 * @param objs
	 * @return
	 */
	public static Map<String,Object> addParamIfNotBlank(Object ...objs) {
		Map<String,Object> map = new HashMap<String,Object>();
		int c = 0;
		if(objs==null||objs.length==0||objs.length%2!=0) {
			throw new RuntimeException("参数个数必须为2的倍数");
		}
		for(int i=0;i<objs.length;i+=2) {
			String key = objs[i].toString();
			Object value_obj = objs[i+1];
			if(value_obj==null) {
				continue;
			}
			if(String.class.isAssignableFrom(value_obj.getClass())) {
				String value = (String)value_obj;
				if(value==null||value.trim().length()==0) {
					continue;
				}
				c++;
				map.put(key, value.trim());
			}
			else
				map.put(key, value_obj);
		}
		return map;
	}
}
